我們上一個專案使用的H2資料庫有個很大的缺點:關閉專案後資料庫的內容會全都消失。
這次我們會使用需要安裝的資料庫,這樣我們的資料就能一直保存下去,關機也不會讓資料消失,如果我們沒有刪除就能一直保存一輩子的資料,是一輩子喔,一輩子。
一談到資料庫,許多人會想到MySQL,因為它和Java是同一家公司(Oracle)的產品,但是在這次的專案不會使用MySQL。
我們來談談Oracle做了什麼事,從前Oracle JDK免費讓所有人和企業使用,突然,Oracle宣佈Oracle JDK要收費了,企業不付錢就律師函警告,Oracle好心提供可以免費商用的Oracle OpenJDK,其他使用Java的企業也開發自己的OpenJDK,現在我們要使用OpenJDK才能免費商用,不小心用到Oracle JDK就只能乖乖付錢。
有了這個前車之鑒,誰能保證MySQL不會突然宣佈要對商業使用付費呢?
為了避開風險,我們選擇用MariaDB,是一個開源專案也可以免費商用,而且有一部分的開發者也曾開發過MySQL。
MariaDB大部分的設計相容MySQL,對於個人開發者來說MariaDB和MySQL幾乎是一樣的。
來到官網下載並安裝,過程相當的簡單,維持預設就好,記住New root password填入的密碼,我們之後會用到。
安裝完成後開啟HeidiSQL,填入之前設定的密碼,點擊開啟。
進入管理頁面,在中間偏上的地方找到查詢,在底下輸入
CREATE DATABASE book;
按下F9,建立book資料庫。
點擊左邊的Unnamed後按下F5,就能看到book資料庫,關閉HeidiSQL。
book entity的格式
欄位名稱 | 資料形態 | 說明 |
---|---|---|
id | Long | 唯一的id,方便資料庫搜尋 |
name | String | 書名 |
page | Integer | 頁數 |
專案的功能
路徑 | HTTP request method | 說明 | Request body |
---|---|---|---|
/ | POST | 新增書籍 | Book |
/all | GET | 取得全部的書籍 | 無 |
/{id} | GET | 取得指定id的書籍 | 無 |
/{id} | PUT | 修改書籍內容 | Book |
/{id} | DELETE | 刪除書籍 | 無 |
前往 Spring Initializr 建立專案,可以參考這張圖。
下載並開啟專案。
在上一個專案我們使用的方法需要打重複的部分,舉例來說:spring.datasource的部分,我們重複打了四次,這邊有另外一種寫法可以省略重複的開頭。
首先把application.properties改名成application.yaml,以下是它的內容
spring:
application:
name: Book-Management-Project
datasource:
#我們從H2改成MariaDB,存放資料的地方也不再是記憶體了。
url: jdbc:mariadb://localhost:3306/book
#選擇MariaDB的驅動程式
driver-class-name: org.mariadb.jdbc.Driver
#MariaDB預設的使用者名稱是root
username: root
#MariaDB的密碼,之前進入管理頁面時用的,不是要你填密碼兩個字。
password: 密碼
jpa:
hibernate:
ddl-auto: update
show-sql: true
yaml對中文註解友善,不像properties寫中文註解,儲存後都變成?
不過YAML對排版很嚴格,空格很重要,和python一樣少一個indent都會導致錯誤。
不論是properties還是YAML都能讓專案運作,選擇哪種就看個人的喜好了。
接下來是寫Entity、Repository、Service、Controller的部分,和上一個專案類似。
//Book.java
@Entity
public class Book {
@Id//表示這個是id也是主鍵
@GeneratedValue(strategy = GenerationType.IDENTITY)//會在資料庫添加AUTO_INCREMENT
private Long id;
private String name;
private int page;
public Book(){
}
public Book(Long id, String name, int page) {
this.id = id;
this.name = name;
this.page = page;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
}
Book是我們的entity,Long是id的資料型態。
//BookRepository.java
public interface BookRepository extends JpaRepository<Book, Long> {
}
這邊和上一個專案有點不同,當我們嘗試去尋找、修改、刪除不存在的id時不會出現錯誤,會回傳空的內容(null)。
//BookService.java
@Service
public class BookService {
private final BookRepository bookRepository;
public BookService(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
將從controller取得的book,儲存到資料庫中,把資料庫儲存後的結果回傳給controller
public Book addBook(Book book) {
return bookRepository.save(book);
}
取得資料庫中所有的book,回傳給controller
public List<Book> getAllBooks() {
return bookRepository.findAll();
}
根據提供的id編號在資料庫中尋找book
public Book getBookById(Long id) {
Optional<Book> opt = bookRepository.findById(id);
return opt.orElse(null);
}
根據提供的id編號修改對應的book
public Book updateBook(Book book) {
Optional<Book> opt = bookRepository.findById(book.getId());
if (opt.isPresent()) {
Book updatedBook = opt.get();
updatedBook.setName(book.getName() == null ? updatedBook.getName() : book.getName());
updatedBook.setPage(book.getPage());
return bookRepository.save(updatedBook);
}
return null;
}
根據提供的id編號在資料庫中刪除book
public void deleteBookById(Long id) {
Optional<Book> opt = bookRepository.findById(id);
opt.ifPresent(book -> bookRepository.deleteById(book.getId()));
}
}
設定BookController中的所有網址的開頭都是/api/book
//BookController.java
@RestController
@RequestMapping("/api/book")
public class BookController {
private final BookService bookService;
public BookController(BookService bookService) {
this.bookService = bookService;
}
新增book,並將新增的book資訊回傳
@PostMapping("/")
public ResponseEntity<Book> addBook(@RequestBody Book book) {
return new ResponseEntity<>(bookService.addBook(book), HttpStatus.CREATED);
}
將資料庫中所有的book回傳
@GetMapping("/all")
public ResponseEntity<List<Book>> getAllBooks() {
return ResponseEntity.ok(bookService.getAllBooks());
}
將指定的book內容回傳
@GetMapping("/{id}")
public ResponseEntity<Book> getBookById(@PathVariable("id") Long id) {
return ResponseEntity.ok(bookService.getBookById(id));
}
修改指定的book內容
@PutMapping("/{id}")
public ResponseEntity<Book> updateBook(@PathVariable("id") Long id, @RequestBody Book book) {
book.setId(id);
return ResponseEntity.ok(bookService.updateBook(book));
}
將指定的book刪除
@DeleteMapping("/{id}")
public ResponseEntity<String> deleteBook(@PathVariable("id") Long id) {
bookService.deleteBookById(id);
return ResponseEntity.ok("Book deleted successfully");
}
}
這裡面少了application.yaml,需要自己建立,可以參考YAML那段的設定。
https://mega.nz/file/1MV33A6Z#BA1TRcFJRYLBCmiAgmjW0UT1NOxzylZ9ggNkQIMLxgs
在這邊提供測試用的範例,可以自行下載,內容我已經設定好了,只需要按下Send,確認結果就好。
我們按照順序測試專案,和上一個專案相同,使用的是Hoppscotch。
建立書籍
取得全部書籍
取得指定id的書
修改指定id書籍資料
刪除指定id的書